
#include "AWorld.h"
#include "AStage.h"
#include "AStageLayer.h"
#include "AUserData.h"
#include "AXML.h"
#include "AString.h"
#include "AUtils.h"

CAWorld * CAWorld::sm_pSharedWorld = NULL;

CAWorld::CAWorld(void)
{
	GUARD_FUNCTION();

	//autorelease();
	sm_pSharedWorld = this;
	//_pLastScene = null;
	_currentStage = null; 
	_pFadeTable = new CAStringMap<CAFadeRecord>();

	_pUserData = new CAUserData();
	int n = CAUserData::sharedUserData().getInteger("run");
	CAUserData::sharedUserData().setInteger("run", n + 1);

	CCLOGINFO("CAWorld created\n");
}

CAWorld::~CAWorld(void)
{
	_pUserData->release();
	_pUserData = null;

	_pFadeTable->release();
	_pFadeTable = null;
	CCLOGINFO("CAWorld released\n");
}

void CAWorld::switchStage(CAStage* pstage)
{
	_Assert(pstage);
	_Assert(pstage->getLoadPercent() == 1.0f);

	CCScene* psNew = CCScene::node();
	// add layer as a child to scene
	psNew->addChild(pstage);

	// run
	if (null == _currentStage)
	{
		CCDirector::sharedDirector()->runWithScene(psNew);
	}
	else
	{
		//_Assert(_pLastScene->getChildrenCount() == 1);
		//CAStage* pLastStage = (CAStage*)_pLastScene->getChildren()->objectAtIndex(0);
		CAStage* pLastStage = _currentStage;
		CAString nameTrans = pLastStage->name() + "-" + pstage->name();
		CAString trans = "";
		float duration = 0.1f;
		CAFadeRecord* pfade = _pFadeTable->objectForKey(nameTrans);
		if (pfade)
		{
			duration = pfade->duration;
			trans = pfade->trans;
		}
		//_currentStage->freaze();
		//CCDirector::sharedDirector()->setDepthTest(false);
	
		CCScene* psTrans = null;
		if ("slide_left" == trans)
		{
			psTrans =  CCTransitionSlideInR::transitionWithDuration(duration, psNew);
		}
		else if ("slide_right" == trans)
		{
			psTrans =  CCTransitionSlideInL::transitionWithDuration(duration, psNew);
		}
		else if ("slide_top" == trans)
		{
			psTrans =  CCTransitionSlideInB::transitionWithDuration(duration, psNew);
		}
		else if ("slide_bottom" == trans)
		{
			psTrans =  CCTransitionSlideInT::transitionWithDuration(duration, psNew);
		}
		else if ("fade_black" == trans)
		{
			psTrans = CCTransitionFade::transitionWithDuration(duration, psNew, ccBLACK); 
		}
		else if ("fade_white" == trans)
		{
			psTrans = CCTransitionFade::transitionWithDuration(duration, psNew, ccWHITE); 
		}
		else if ("fade_tr" == trans)
		{
			psTrans = CCTransitionFadeTR::transitionWithDuration(duration, psNew); 
		}
		else if ("fade_bl" == trans)
		{
			psTrans = CCTransitionFadeBL::transitionWithDuration(duration, psNew); 
		}
		else if ("fade_up" == trans)
		{
			psTrans = CCTransitionFadeUp::transitionWithDuration(duration, psNew); 
		}
		else if ("fade_down" == trans)
		{
			psTrans = CCTransitionFadeDown::transitionWithDuration(duration, psNew); 
		}
		else
		{
			//_Assert(false);
			_Trace("warnning: can not find trans for %s", nameTrans.c_str());
			psTrans = psNew;
		}
		CCDirector::sharedDirector()->replaceScene(psTrans);
	}

	_currentStage = pstage;
	// return the scene
	return;
}

void CAWorld::_setFPS(float fps)
{
	CCDirector* pDirector = CCDirector::sharedDirector();

	if (fps < 20.0f) fps = 20.0f; 
	else if (fps > 60.0f) fps = 60.0f;

	pDirector->setAnimationInterval(1.0 / fps);
}

void CAWorld::_loadSettings(CAXMLNode* pnode)
{
	_Assert(pnode);

	CCObject* pitem;
	CAXMLNodes* pnodes;
	
	pnodes = pnode->nodes("key");
	_Assert(pnodes);

	CCARRAY_FOREACH(pnodes, pitem)
	{
		CAXMLNode* pnodeItem = (CAXMLNode*)pitem;
		CAString name = pnodeItem->attr("name");
		if (name == "fps")
		{
			float fps = 30.0f;
			CAStringUtils::toFloat(pnodeItem->attr("float"), fps);
			_setFPS(fps);
		}
		else if (name == "log")
		{
			int ll = 0;
			CAStringUtils::toInt(pnodeItem->attr("int"), ll);
			CADebug::setTraceLevel((ELogLevel)ll);
		}
	}
}

void CAWorld::_loadFadeTable(CAXMLNode* pnode)
{
	GUARD_FUNCTION();

	_Assert(pnode);

	CCObject* pitem;
	CAXMLNodes* pnodes;
	
	pnodes = pnode->nodes("fade");
	_Assert(pnodes);
	CCARRAY_FOREACH(pnodes, pitem)
	{
		GUARD_FIELD(_fade_record);
	
		CAXMLNode* pnodeItem = (CAXMLNode*)pitem;

		CAFadeRecord* pfr = new CAFadeRecord;

		pfr->from = pnodeItem->attr("from");
		pfr->to = pnodeItem->attr("to");
		pfr->duration = 0.5f;
		CAStringUtils::toFloat(pnodeItem->attr("duration"), pfr->duration);
		pfr->trans = pnodeItem->attr("trans");

		_pFadeTable->setObject(pfr, pfr->from + "-" + pfr->to);
	}
}

int CAWorld::initialize()
{
	GUARD_FUNCTION();

	CAXMLNode* pxml = CAXML::parse("game.world", false);
	_Assert(pxml);
	CAXMLNode* pnode;
	pnode = pxml->firstnode("world");
	_Assert(pnode);

	_loadFadeTable(pnode->firstnode("fadetable"));

	_loadSettings(pnode->firstnode("settings"));

	return 0;
}

CCSize CAWorld::getScreenSize()
{
	return CCDirector::sharedDirector()->getWinSize();
}

void CAWorld::dispatchEvent(ESystemEvent evt, void* data)
{
	if (_currentStage)
	{
		_currentStage->onSystemEvent(evt, data);
	}
}
